home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / ppcuuwos.lha / PPCUUDecode.c < prev    next >
C/C++ Source or Header  |  1998-02-18  |  7KB  |  244 lines

  1.  
  2. /*
  3.  * uudecode [input]
  4.  *
  5.  * Decode a file encoded with uuencode.  Will extract multiple encoded
  6.  * modules from a single file.  Can deal with most mangled files, including
  7.  * those that have been mangled by common BITNET problems.
  8.  *
  9.  */
  10.  
  11. /* Modified by Steffen P. Häuser (ELF-Version was from Andreas Kleinert)
  12.  *
  13.  * 18.02.98: - WarpOS (TM) version, compiled with StormC, as ELF sucks :)
  14.  *
  15.  * 07.02.98: - powerUP (TM) version, compiled with SAS/C for PPC
  16.  *
  17.  * 31.08.97: - reworked for SAS/C 6.58
  18.  *           - better compiler settings
  19.  *           - ANSI-fied
  20.  *
  21.  * 04.08.94: - first, internal version
  22.  *
  23.  *
  24.  *
  25.  * Original authors:
  26.  *
  27.  * Written by Mark Horton
  28.  * Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums
  29.  * Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  30.  * compatibility
  31.  * Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a misleading
  32.  * error message on the Amiga port, to fix a bug that prevented decoding
  33.  * certain files, to work even if trailing spaces have been removed from a
  34.  * file, to check the filesize (if present), to add some error checking, to
  35.  * loop for multiple decodes from a single file, and to handle common
  36.  * BITNET mangling.  Kludged around a missing string function in Aztec
  37.  * C. Changed "r" to "rb" and "w" to "wb" for Messy-dos machines
  38.  * (Thanks to Andrew Wylie).
  39.  */
  40.  
  41. #define __USE_SYSBASE
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46.  
  47. #include <ctype.h>
  48.  
  49. #include <sys/types.h>
  50. #include <sys/stat.h>
  51.  
  52. #include <exec/types.h>
  53.  
  54. #include <clib/exec_protos.h>
  55.  
  56. void decode(FILE *in, FILE *out, UBYTE *dest);
  57.  
  58. UBYTE version [] = "\0$VER: uudecode 1.0 (7.2.98)";
  59.  
  60. long main(long argc, char **argv)
  61. {
  62.  FILE *in, *out;
  63.  LONG through_loop = 0; /* Dejavu indicator */
  64.  LONG mode;             /* file's mode (from header) */
  65.  LONG filesize;         /* theoretical file size (from header) */
  66.  UBYTE dest[128];
  67.  UBYTE buf[80];
  68.  
  69.     /* A filename can be specified to be uudecoded, or nothing can
  70.     be specified, and the input will come from STDIN */
  71.  
  72.     switch (argc)
  73.         {
  74.         case 1:
  75.         in=stdin;
  76.         break;
  77.  
  78.         case 2:
  79.         if ((in = fopen(argv[1], "r")) == NULL)
  80.             {
  81.             fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
  82.             fprintf(stderr, "USAGE: uudecode [infile]\n");
  83.             exit(20);
  84.             }
  85.         break;
  86.  
  87.         default:
  88.         fprintf(stderr, "USAGE: uudecode [infile]\n");
  89.         exit(0);
  90.         break;
  91.         }
  92.  
  93.     /* Loop through file, searching for headers.  Decode anything with a
  94.        header, complain if there where no headers. */
  95.  
  96. for (;;)
  97. {
  98.     /* search file for header line */
  99.     for (;;)
  100.         {
  101.         if (fgets(buf, sizeof buf, in) == NULL)
  102.             {
  103.             if (!through_loop)
  104.                 {
  105.                 fprintf(stderr, "ERROR: no `begin' line!\n");
  106.                 exit(20);
  107.                 }
  108.             else
  109.                 {
  110.                 exit(0);
  111.                 }
  112.             }
  113.         if (strncmp(buf, "begin ", 6) == 0)
  114.             break;
  115.         }
  116.     sscanf(buf, "begin %o %s", &mode, dest);
  117.  
  118.     /* create output file */
  119.     if ((out = fopen(dest, "w")) == NULL)
  120.         {
  121.         fprintf(stderr, "ERROR: can't open output file %s\n", dest);
  122.         exit(20);
  123.         }
  124.  
  125.     decode(in, out, dest);
  126.  
  127.     if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3))
  128.         {              /* don't be overly picky about newline ^ */
  129.         fprintf(stderr, "ERROR: no `end' line\n");
  130.         exit(20);
  131.         }
  132.  
  133.     if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3)))
  134.         {
  135.         sscanf(buf, "size %ld", &filesize);
  136.         if (ftell(out) != filesize)
  137.             {
  138.             fprintf(stderr, "ERROR: file should have been %ld bytes long but was %ld.\n", filesize, ftell(out));
  139.             exit(20);
  140.             }
  141.         }
  142.     through_loop = 1;
  143. }   /* forever */
  144.  
  145.  exit(0);
  146. }
  147.  
  148. #define SUMSIZE 64
  149. #define DEC(c)  (((c) - ' ') & 077)    /* single character decode */
  150.  
  151. /*
  152.  * Copy from in to out, decoding as you go.
  153.  * If a return or newline is encountered too early in a line, it is
  154.  * assumed that means that some editor has truncated trailing spaces.
  155.  */
  156. void decode(FILE *in, FILE *out, UBYTE *dest)
  157. {
  158.  extern errno;
  159.  
  160.  UBYTE *bp;
  161.  LONG nosum=0;
  162.  LONG j, n, checksum, line;
  163.  UBYTE buf[256];
  164.  
  165.     for (line = 1; ; line++)    /* for each input line */
  166.         {
  167.         if (fgets(buf, sizeof buf, in) == NULL)
  168.             {
  169.             fprintf(stderr, "ERROR: input ended unexpectedly!\n");
  170.             exit(20);
  171.             }
  172.  
  173.         /* Pad end of lines in case some editor truncated trailing
  174.            spaces */
  175.  
  176.         for (n=0;n<79;n++)  /* search for first \r, \n or \000 */
  177.             {
  178.             if (buf[n]=='\176')     /* If BITNET made a twiddle, */
  179.                 buf[n]='\136';     /* we make a caret           */
  180.             if (buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000')
  181.                 break;
  182.             }
  183.         for (;n<79;n++)     /* when found, fill rest of line with space */
  184.             {
  185.             buf[n]=' ';
  186.             }
  187.         buf[79]=0;          /* terminate new string */
  188.  
  189.         checksum = 0;
  190.         n = DEC(buf[0]);
  191.         if (n <= 0)
  192.             break;      /* 0 bytes on a line??  Must be the last line */
  193.  
  194.         bp = &buf[1];
  195.  
  196.         /* FOUR input characters go into each THREE output charcters */
  197.  
  198.         while (n >= 4)
  199.             {
  200.             j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; putc(j, out); checksum += j;
  201.             j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; putc(j, out); checksum += j;
  202.             j = DEC(bp[2]) << 6 | DEC(bp[3]);      putc(j, out); checksum += j;
  203.             checksum = checksum % SUMSIZE;
  204.             bp += 4;
  205.             n -= 3;
  206.             }
  207.  
  208.             j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  209.                 checksum += j;
  210.                 if (n >= 1)
  211.                     putc(j, out);
  212.             j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  213.                 checksum += j;
  214.                 if (n >= 2)
  215.                     putc(j, out);
  216.             j = DEC(bp[2]) << 6 | DEC(bp[3]);
  217.                 checksum += j;
  218.                 if (n >= 3)
  219.                     putc(j, out);
  220.             checksum = checksum % SUMSIZE;
  221.             bp += 4;
  222.             n -= 3;
  223.  
  224.          /* Error checking under UNIX??? You must be kidding... */
  225.          /* Check if an error occured while writing to that last line */
  226.         if (errno)
  227.             {
  228.             fprintf(stderr, "ERROR: error writing to %s\n",dest);
  229.             exit(20);
  230.             }
  231.  
  232.         /* The line has been decoded; now check that sum */
  233.  
  234.         nosum |= !isspace(*bp);
  235.         if (nosum)                      /* Is there a checksum at all?? */
  236.             {
  237.             if (checksum != DEC(*bp))   /* Does that checksum match? */
  238.                 {
  239.                 fprintf(stderr, "ERROR: checksum mismatch decoding %s, line %d.\n",dest, line);
  240.                 }
  241.             }   /* sum */
  242.     }   /* line */
  243. }   /* function */
  244.